var app = require('http').createServer()
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , mysql = require('mysql');

 var connection;
 var socketList = [];
 
 var socketStatus = [];
 var socketQueue = [];
 
io.configure('production', function() {
    io.enable('browser client etag');
    io.set('log level', 1);
    io.set('transports', [
        'websocket'
        , 'flashsocket'
        , 'htmlfile'
        , 'xhr-polling'
        , 'jsonp-polling'
        ]);
});

io.configure('development', function() {
    io.set('transports', ['websocket', 'htmlfile' , 'jsonp-polling']);
    io.set('destroy upgrade', false);
});

app.listen(8000);
//app.listen(8000,'172.22.194.22');

connection= mysql.createConnection({
    //host:'10.33.247.66',
    host:'localhost',
    port: 3306,
    user:'root',
    password:'',
    database:'sapfeed',
    debug:true,
    multipleStatements: true
});
		
connection.connect( function (err) {
    if(!err)
        console.log('Connected');
    else
        console.log(err);
});
io.sockets.on('connection', function (socket) {
	
	
	socket.on('publish', function( publishInfo ) {

            socketQueue[socket.id].push({action: publish, parameter: publishInfo});
            if(!socketStatus[socket.id]){
                runNextFunction();
            }

	});
	
	socket.on('listen', function ( listenInfo ) {
            socketQueue[socket.id].push({action: listen, parameter: listenInfo});
            if(!socketStatus[socket.id]){
                runNextFunction();
            }
                
	});
	

        
        socket.on('logout_request', function(logoutInfo){
            socketQueue[socket.id].push({action: logout, parameter: logoutInfo});
            if(!socketStatus[socket.id]){
                runNextFunction();
            }        
            
        });
	
	socket.on('disconnect', function () {
            delete socketList[socket.id];
	});


    socket.on('login_request', function( loginInfo ) {

        var getUserSql = 'SELECT id FROM user WHERE id =' + loginInfo.userID + ' AND password ="' + loginInfo.password + '" ;';
        connection.query(getUserSql, function(err, results) {
            if(err){
                socket.emit('login_failure',{
                    activityID: loginInfo.activityID,
                    code: "E003",
                    message: "Server Side Error"
                });
            }
            else{
                if(results&&results[0]) {
                    var addCurrent = 'INSERT INTO user_socket SET user_id=' + results[0].id + ', socket_id="'+ socket.id + '";';
                    connection.query( addCurrent, function( err2, result) {
                        if(err2) {
                            socket.emit('login_failure',{
                                activityID: loginInfo.activityID,
                                code: "E003",                                
                                message: "Server Side Error"
                            });
                        } else {
                            socketList[socket.id] = socket;
                            socketQueue[socket.id] = [];
                            socketStatus[socket.id] = false;
                            console.log('Result : ' + result);

                            socket.emit('login_success',{
                                activityID: loginInfo.activityID,
                                code: "P101",                                
                                message: "Login Success"
                            });
                            
                                                
                        }
                    });
                }
                else{
                    socket.emit('login_failure',{
                        activityID: loginInfo.activityID,
                        code: "E102",                        
                        message: "Invalid Combination of User ID and Password"
                    });
                }
            }
        });
    //if record found, update database with new socket.id
    });

    function publish(publishInfo){
        
        var datasetNum = publishInfo.datasetList.length;
        var findPublisherIDSQL = 'SELECT publisher.id FROM publisher INNER JOIN user_socket ON user_socket.user_id = publisher.user_id WHERE user_socket.socket_id = "'+socket.id+'"';
        var publisherID;
                
        connection.query(findPublisherIDSQL,function(err, results){
            if(err){
                    socket.emit('publish_failure',{
                        activityID: publishInfo.activityID,
                        code: "E003",                          
                        message: "Server Side Error"
                    });
                    
                    handOver();
                    //end point
                    
            }
            else{
                if(results&&results[0]){
                    publisherID = results[0].id;
                    var checkPublishRightSQL="SELECT 1 ; ";
                    var i;


                    for(i=0;i<datasetNum;i++){
                        checkPublishRightSQL = checkPublishRightSQL + 'SELECT publisher_id FROM dataset_publisher WHERE publisher_id='+publisherID+' AND dataset_id='+publishInfo.datasetList[i]+' ; ';
                    }
                    connection.query(checkPublishRightSQL,function(err2, results2){

                        if(err2){
                                socket.emit('publish_failure',{
                                    activityID: publishInfo.activityID,
                                    code: "E003",                          
                                    message: "Server Side Error"
                                });
                                handOver();
                                //end point
                        }
                        else{
                            
                            var getSocketsSQL="SELECT 1 ; ";
                            var accessTest = true;
                            for(i=1;i<results2.length;i++){
                                if(results2[i]&&results2[i][0]){
                                    getSocketsSQL = getSocketsSQL + 'SELECT socket_listen_status.socket_id FROM socket_listen_status WHERE socket_listen_status.dataset_id = '+publishInfo.datasetList[i-1]+' AND socket_listen_status.socket_id IN (SELECT user_socket.socket_id FROM user_socket INNER JOIN user ON user_socket.user_id = user.id INNER JOIN consumer ON user.id = consumer.user_id INNER JOIN dataset_consumer ON dataset_consumer.consumer_id = consumer.id WHERE dataset_consumer.dataset_id = '+publishInfo.datasetList[i-1] +')';
                                }
                                else{
                                    accessTest = false;
                                }
                            }
                            
                            var getUnrelatedSocketsSQL = "SELECT 1 ;";
                            for(i=1;i<results2.length;i++){
                                if(results2[i]&&results2[i][0]){
                                    getUnrelatedSocketsSQL = getUnrelatedSocketsSQL + 'SELECT socket_listen_status.socket_id FROM socket_listen_status WHERE socket_listen_status.dataset_id = '+publishInfo.datasetList[i-1]+' AND socket_listen_status.socket_id NOT IN (SELECT user_socket.socket_id FROM user_socket INNER JOIN user ON user_socket.user_id = user.id INNER JOIN consumer ON user.id = consumer.user_id INNER JOIN dataset_consumer ON dataset_consumer.consumer_id = consumer.id WHERE dataset_consumer.dataset_id = '+publishInfo.datasetList[i-1] +')';
                                }
                            }                            
                            
                            if(accessTest){
                            
                                connection.query(getSocketsSQL, function(err3, results3){
                                    if(err3){
                                        socket.emit('publish_failure',{
                                            activityID: publishInfo.activityID,
                                            code: "E003",                          
                                            message: "Server Side Error"
                                        }); 
                                        handOver();
                                        //end point
                                    }
                                    else{
                                        var j,m;
                                        var logSQL = 'SELECT 1=1; ';
                                        for(j=1;j<results3.length;j++){
                                            for(m=0;m<results3[j].length;m++){
                                                socketList[results3[j][m].socket_id].emit('data_transfer',{
                                                    publisher: publisherID,
                                                    dataset: publishInfo.datasetList[j-1],
                                                    data:publishInfo.data
                                                    });
                                                logSQL = logSQL + 'INSERT INTO consumption_log SET publisher_id = '+publisherID+' , consumer_id = (SELECT consumer.id FROM consumer INNER JOIN user_socket ON user_socket.user_id = consumer.user_id WHERE user_socket.socket_id = "'+results3[j][m].socket_id+'") , dataset_id='+publishInfo.datasetList[j-1]+' , quantity = 1, timestamp = '+(new Date()).getTime()+' ;';
                                            }
                                        }
                                        
                                        connection.query(logSQL, function(err4, results4){
                                            if(err4){
                                                socket.emit('publish_success',{
                                                    activityID: publishInfo.activityID,
                                                    code: "P302",                          
                                                    message: "Publish Success with Minor Error"
                                                }); 
                                                
                                                connection.query(getUnrelatedSocketsSQL, function(err5, results5){
                                                    var h,k;
                                                    for(h=1;h<results5.length;h++){
                                                        for(k=0;k<results5[h].length;k++){
                                                            socketList[results5[h][k].socket_id].emit('setting_change',{
                                                                code: "E999",                          
                                                                message: "Setting Changed"
                                                            });
                                                        }
                                                    }
                                                });
                                                
                                                handOver();
                                                //end point                                                
                                            }
                                            else{
                                                socket.emit('publish_success',{
                                                    activityID: publishInfo.activityID,
                                                    code: "P301",                          
                                                    message: "Publish Success"
                                                });
                                            
                                                connection.query(getUnrelatedSocketsSQL, function(err5, results5){
                                                    var h,k;
                                                    for(h=1;h<results5.length;h++){
                                                        for(k=0;k<results5[h].length;k++){
                                                            socketList[results5[h][k].socket_id].emit('setting_change',{
                                                                code: "E999",                          
                                                                message: "Setting Changed"
                                                            });
                                                        }
                                                    }
                                                });                                                
                                                
                                                handOver();
                                                //end point
                                            }
                                        });
                                        
                                    }
                                });
                                
                                
                                
                            }
                            else{
                                socket.emit('publish_failure',{
                                    activityID: publishInfo.activityID,
                                    code: "E301",                                       
                                    message: "No Publish Rights to Certain Dataset(s)"
                                });
                            handOver();    
                            //end point
                            }
                            
                        }


                    });

                }
                else{
                    socket.emit('publish_failure',{
                        activityID: publishInfo.activityID,
                        code: "E302",                            
                        message: "Publish without Publisher Identity"
                    });
                    handOver();
                    //end point
                }
            }
        });
        
        
                    
    }        
    
    function listen(listenInfo){
        //subscriber listens to data sets in dataSetList
        var datasetNum = listenInfo.datasetList.length;
                
        var findConsumerIDSQL = 'SELECT consumer.id FROM consumer INNER JOIN user_socket ON user_socket.user_id = consumer.user_id WHERE user_socket.socket_id = "'+socket.id+'"';
        var consumerID;
                
        connection.query(findConsumerIDSQL,function(err, results){
            if(err){
                    socket.emit('listen_failure',{
                        activityID: listenInfo.activityID,
                        code: "E003",                          
                        message: "Server Side Error"
                    });
                    
                    handOver();
                    //end point
                    
            }
            else{
                if(results&&results[0]){
                    consumerID = results[0].id;
                    var checkListenRightSQL="SELECT 1 ; ";
                    var i;


                    for(i=0;i<datasetNum;i++){
                        checkListenRightSQL = checkListenRightSQL + 'SELECT consumer_id FROM dataset_consumer WHERE consumer_id='+consumerID+' AND dataset_id='+listenInfo.datasetList[i]+' ; ';
                    }
                    connection.query(checkListenRightSQL,function(err2, results2){

                        if(err2){
                                socket.emit('listen_failure',{
                                    activityID: listenInfo.activityID,
                                    code: "E003",                          
                                    message: "Server Side Error"
                                });
                                handOver();
                                //end point
                        }
                        else{
                            
                            var insertSocketsSQL="";
                            var accessTest = true;
                            for(i=1;i<results2.length;i++){
                                if(results2[i]&&results2[i][0]){
                                    insertSocketsSQL = insertSocketsSQL + 'INSERT INTO socket_listen_status SET dataset_id = '+listenInfo.datasetList[i-1]+' , socket_id="'+socket.id+'"'+' ; ';
                                }
                                else{
                                    accessTest = false;
                                }
                            }
                            
                            if(accessTest){
                            
                                connection.query(insertSocketsSQL, function(err3, results3){
                                    if(err3){
                                        socket.emit('listen_failure',{
                                            activityID: listenInfo.activityID,
                                            code: "E003",                          
                                            message: "Server Side Error"
                                        }); 
                                        handOver();
                                        //end point
                                    }
                                    else{
                                        socket.emit('listen_success',{
                                            activityID: listenInfo.activityID,
                                            code: "P401",                          
                                            message: "Listen Success"                                            
                                        });
                                        handOver();
                                        //end point
                                    }
                                });
                            }
                            else{
                                socket.emit('listen_failure',{
                                    activityID: listenInfo.activityID,
                                    code: "E401",                                       
                                    message: "No Listen Rights to Certain Dataset(s)"
                                });
                            handOver();    
                            //end point
                            }
                            
                        }


                    });

                }
                else{
                    socket.emit('listen_failure',{
                        activityID: listenInfo.activityID,
                        code: "E402",                                       
                        message: "Listen without Listener Identity"
                    });
                    handOver();
                    //end point
                }
            }
        });
         
    }
    
    function logout(logoutInfo){
        var deleteUserSocket = 'DELETE FROM user_socket WHERE socket_id="'+socket.id+'";';
        connection.query( deleteUserSocket, function( err, result) {
            if(err) {
                console.log('Error : ' + err);
                socket.emit('logout_failure',{
                    activityID: logoutInfo.activityID,
                    code: "E003",                          
                    message: "Server Side Error"
                });
            } else {
                var deleteSocketListen = 'DELETE FROM socket_listen_status WHERE socket_id="'+socket.id+'";';
                connection.query( deleteSocketListen, function( err, result) {
                    if(err) {
                        console.log('Error : ' + err);
              
                        socket.emit('logout_failure',{
                            activityID: logoutInfo.activityID,
                            code: "E003",                                       
                            message: "Server Side Error"
                        });
                    } else {
                        console.log('Result : ' + result);
                        delete socketStatus[socket.id];
                        delete socketQueue[socket.id];
                        socket.emit('logout_success',{
                            activityID: logoutInfo.activityID,
                            code: "P201",                                       
                            message: "Logout Success"                            
                        });
                    }
                });    
            }
        });
      
    }
    
     
     
    function runNextFunction(){
        
        console.log(socketQueue[socket.id])
        
        if(socketQueue[socket.id][0]){
            var action = socketQueue[socket.id][0].action;
            var para = socketQueue[socket.id][0].parameter;
            socketStatus[socket.id] = true;
            
//            
//            if(action=='publish'){
//                publish(para);
//            }

            action(para);
            
        }
    }
    
    function finishCurrentFunction(){
        socketQueue[socket.id].shift();
        socketStatus[socket.id] = false;
    }
    
    function handOver(){
        
        console.log("*****************handover begins*****************")
        
        finishCurrentFunction();
        runNextFunction();
        
        console.log("*****************handover ends*****************")
    }
     
     
});

